namespace A1Tests;

using A1;

public class OrderServiceTests
{
    [Fact]
    public void AddOrder_WithUniqueOrderId_AddsOrder()
    {
        var service = new OrderService();
        var order = new Order(1, new Customer("Customer A"), new List<OrderDetails>());

        service.AddOrder(order);

        Assert.Contains(order, service.GetAllOrders());
    }

    [Fact]
    public void AddOrder_WithExistingOrderId_ThrowsException()
    {
        var service = new OrderService();
        var order = new Order(1, new Customer("Customer A"), new List<OrderDetails>());
        service.AddOrder(order);

        var duplicateOrder = new Order(1, new Customer("Customer B"), new List<OrderDetails>());

        Assert.Throws<Exception>(() => service.AddOrder(duplicateOrder));
    }

    [Fact]
    public void RemoveOrder_WithExistingOrderId_RemovesOrder()
    {
        var service = new OrderService();
        var order = new Order(1, new Customer("Customer A"), new List<OrderDetails>());
        service.AddOrder(order);

        service.RemoveOrder(1);

        Assert.DoesNotContain(order, service.GetAllOrders());
    }

    [Fact]
    public void RemoveOrder_WithNonExistingOrderId_ThrowsException()
    {
        var service = new OrderService();

        Assert.Throws<Exception>(() => service.RemoveOrder(999));
    }

    [Fact]
    public void ReplaceOrder_WithExistingOrderId_ReplacesOrder()
    {
        var service = new OrderService();
        var originalOrder = new Order(1, new Customer("Customer A"), new List<OrderDetails>());
        service.AddOrder(originalOrder);

        var newOrder = new Order(1, new Customer("Customer B"), new List<OrderDetails>());
        service.ReplaceOrder(1, newOrder);

        Assert.Contains(newOrder, service.GetAllOrders());
        Assert.DoesNotContain(originalOrder, service.GetAllOrders());
    }

    [Fact]
    public void ReplaceOrder_WithNonExistingOrderId_ThrowsException()
    {
        var service = new OrderService();
        var newOrder = new Order(999, new Customer("Customer A"), new List<OrderDetails>());

        Assert.Throws<Exception>(() => service.ReplaceOrder(999, newOrder));
    }

    [Fact]
    public void QueryOrders_WithPredicate_ReturnsFilteredOrders()
    {
        var service = new OrderService();
        var order1 = new Order(1, new Customer("Customer A"), new List<OrderDetails>
        {
            new OrderDetails(new Product("Product A", 100), 2)
        });
        var order2 = new Order(2, new Customer("Customer B"), new List<OrderDetails>
        {
            new OrderDetails(new Product("Product B", 200), 1)
        });
        service.AddOrder(order1);
        service.AddOrder(order2);

        var result = service.QueryOrders(o => o.Customer.Name == "Customer A");

        Assert.Contains(order1, result);
        Assert.DoesNotContain(order2, result);
    }

    [Fact]
    public void Export_Then_Import_RoundTrip()
    {
        var service = new OrderService();
        var order = new Order(1, new Customer("Customer A"), new List<OrderDetails>());
        service.AddOrder(order);

        string filePath = Path.GetTempFileName();
        try
        {
            service.Export(filePath);
            var importService = new OrderService();
            importService.Import(filePath);

            var importedOrders = importService.GetAllOrders();
            Assert.Contains(importedOrders, o => o.OrderId == order.OrderId);
        }
        finally
        {
            File.Delete(filePath);
        }
    }

    [Fact]
    public void Import_WithDuplicateOrderIds_ThrowsException()
    {
        var service = new OrderService();
        var order = new Order(1, new Customer("Customer A"), new List<OrderDetails>());
        service.AddOrder(order);

        string filePath = Path.GetTempFileName();
        try
        {
            service.Export(filePath);
            Assert.Throws<Exception>(() => service.Import(filePath));
        }
        finally
        {
            File.Delete(filePath);
        }
    }

    [Fact]
    public void GetAllOrders_ReturnsAllOrdersOrderedById()
    {
        var service = new OrderService();
        var order1 = new Order(2, new Customer("Customer B"), new List<OrderDetails>());
        var order2 = new Order(1, new Customer("Customer A"), new List<OrderDetails>());
        service.AddOrder(order1);
        service.AddOrder(order2);

        var allOrders = service.GetAllOrders();

        Assert.Equal(2, allOrders.Count);
        Assert.Equal(1, allOrders[0].OrderId);
        Assert.Equal(2, allOrders[1].OrderId);
    }
}